#pragma once
#ifndef H_CHARACTER
#define H_CHARACTER
#include "precompiled.h"
#include "equipcom.h"
#include "itemdatabase.h"
#include "buff.h"
#include "enchant.h"
#include "httpget.h"
#include "characterfactory.h"
namespace weo
{
    namespace engine
    {
        namespace
        {
            void InitChar();
            std::map<std::string,unsigned int> ClassMap;
            static const std::string classes[] = {"None", "Shaman", "Priest", "Mage", "Warrior", "Rogue","Hunter", "Paladin","Druid","Warlock"};
            static const int classCount = sizeof(classes)/sizeof(std::string);
        }
        namespace character
        {
            struct Equipment
            {
                weo::engine::item::ItemPtr Items[weo::engine::Slotcount];
                weo::engine::item::EnchantPtr Enchants[weo::engine::Slotcount];
                weo::engine::item::GemPtr Gems[weo::engine::Slotcount*3];
                float Fitness;
                void setEquip(const weo::engine::item::ItemPtr items[weo::engine::Slotcount], const weo::engine::item::GemPtr gems[weo::engine::Slotcount*3], const weo::engine::item::EnchantPtr enchants[weo::engine::Slotcount])
                {
                    memcpy(Items,items,sizeof(weo::engine::item::ItemPtr)*weo::engine::Slotcount);
                    memcpy(Gems,gems,sizeof(weo::engine::item::GemPtr)*weo::engine::Slotcount*3);
                    memcpy(Enchants,enchants,sizeof(weo::engine::item::EnchantPtr)*weo::engine::Slotcount);
                    Fitness = 0;
                }
                std::pair<std::string,std::string> getEquipmentFromWeb(std::string url);
                std::pair<std::string,std::string> loadEquipmentFromFile(std::string filename);
                bool saveEquipmentToFile(std::string classname, std::string buildname, std::string filename);
                Equipment& operator=(const Equipment& equip);

            };
            class Character : public gc
            {
                typedef const weo::engine::item::Item* ItemPtr;
                typedef const weo::engine::item::Enchant* EnchantPtr;
                typedef const weo::engine::item::Item* GemPtr;
            private:
                bool filterItemCharacter(const weo::engine::item::Item* item);
            protected:
                bool m_HasBok;
                std::vector<weo::engine::item::Attribute> m_Basevalues;
                const weo::engine::item::Itemdatabase* m_Database;
                weo::engine::character::Equipcom m_Equip;
                unsigned int m_Classnr;
                std::map<std::string,Buff> m_Buffs;	
                std::vector<std::string> m_AttributesVector;
                unsigned int m_AttributesStart;
                unsigned int m_AttributesStop;
                std::vector<weo::engine::item::Attribute>::const_iterator attrit;
                std::set<unsigned int> m_GoodAttributes;
                std::vector<unsigned int> m_CondCache;
                std::set<unsigned int> m_Whitelist;
                std::set<unsigned int> m_Blacklist;
                unsigned int m_FilterBelow;
                unsigned int m_FilterAbove;
                std::map<std::string,bool> m_FilterArea;
                unsigned int m_FilterSource;
                float m_CondFactor;
                std::vector<std::pair<unsigned int, float>> m_Conditions;
                virtual void Init();
                void initBuffs();
            public:
                void Database(const weo::engine::item::Itemdatabase* value) {m_Database = value;};
                virtual void filterEquip(std::vector<std::vector<const weo::engine::item::Item*>>& items);
                virtual float evaluateTF() = 0;
                virtual void handleAttribute(const weo::engine::item::Attribute& attr);
                static unsigned int isAllowed(const std::string& value);			
                static const std::vector<std::string> returnAllowed(const int value);
                unsigned int Classnr() const {return m_Classnr;};
                void Classnr(const unsigned int value) {m_Classnr = value;};			
                void initGoodAttributes();
                Equipcom& Equip() {return m_Equip;};
                virtual float Agi2Crit() = 0;
                virtual float Str2Ap() = 0;
                virtual float Agi2Ap() = 0;
                virtual float Int2Crit() const {return 0.0125f;};
                virtual float Agi2Dodge() const {return 1.0f/30.0f;};
                virtual bool evaluateEquip(const ItemPtr *items, const GemPtr *gems, const EnchantPtr *enchants );
                virtual void evaluteItem(const weo::engine::item::Item& item, const unsigned int slot = 0);
                virtual bool evaluateBuild(unsigned int tree1, unsigned int tree2, unsigned int tree3) = 0;
                std::map<std::string,Buff>* Buffs() {return &m_Buffs;};
                void evaluateBuffs();
                void addAttribute(const weo::engine::item::Attribute& value)
                {
                    m_Equip.Mode(2);
                    handleAttribute(value);
                    m_Equip.Mode(3);
                }
                virtual std::string targetValue() const {return "DPS";};
                const std::vector<std::string>* getAttributes() const {return &m_AttributesVector;};
                virtual unsigned int getAttributesStart() const {return m_AttributesStart;};
                virtual unsigned int getAttributesStop() const {return m_AttributesStop;};
                unsigned int getFilterBelow() const {return m_FilterBelow;};
                unsigned int getFilterAbove() const {return m_FilterAbove;};
                void setFilterBelow(const unsigned int value) {m_FilterBelow = value;};
                void setFilterAbove(const unsigned int value) {m_FilterAbove = value;};
                const std::map<std::string,bool>* getFilterArea() const {return &m_FilterArea;};
                void setFilterArea(const std::map<std::string,bool>& value) {m_FilterArea = value;};
                void toggleFilterArea(const std::string key, bool value) {m_FilterArea[key] = value;};
                const std::vector<const std::pair<std::string,float>> Character::getEquipValues() const;
                const unsigned int getFilterSource() const {return m_FilterSource;};
                void setFilterSource(const unsigned int value) {m_FilterSource = value;};
                const std::set<unsigned int> Whitelist() const {return m_Whitelist;};
                const std::set<unsigned int> Blacklist() const {return m_Blacklist;};
                void setWhitelist(const std::set<unsigned int>& list) {m_Whitelist = list;};
                void setBlacklist(const std::set<unsigned int>& list) {m_Blacklist = list;};
                const std::vector<std::pair<unsigned int, float>> Conditions() const {return m_Conditions;};
                void setConditions(const std::vector<std::pair<unsigned int, float>> value);				
            };
        };
    };
};
#endif